package com.fingard.dsp.bank.directbank.jhbank02;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.directbank.jhbank02.utils.Decipher;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.net.ConnState;
import com.fingard.text.StringHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import org.apache.commons.lang3.StringUtils;

import java.sql.Connection;
import java.util.Map;


/**
 * @ClassName JHBANK02SinglePay
 * @Author Zhengzy
 * @Date 2019/12/2 14:48
 * @Version 1.0
 **/
public class JHBANK02SinglePay extends JHBANK02Base implements ISinglePay {
    private static final String INSERTRECEIPT = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,REQSEQID,BANKREQSEQID) values (?,?,?,?);";
    private static final String SELECTRECEIPT = "SELECT BANKREQSEQID FROM REQSEQIDMAPPING WHERE REQSEQID=? and BANKCODE=?;";


    @Override
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        String cer = getBankConfig().getValueAsString("certificatePath");
        String pfx = getBankConfig().getValueAsString("certificatePfxPath");
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        RetAtsSglDetail detail = new RetAtsSglDetail();
        Connection conn = FGBiz.getLocalDbConn();
        try {
            detail.reqSeqID = p_req1908.singleDetail.askNumber;
            XmlTextWriter xmlTextWriter = new XmlTextWriter();
            JHBANK02Header header = new JHBANK02Header();
            header.userid = bankFront.operator;
            String nodeNo = getBankConfig().getValueAsString("nodeNo");
            header.brchno = nodeNo;
            header.servtp = "";
            header.prcscd = "YQCZ03";
            writeCommenHeader(xmlTextWriter, header);
            XElement body = new XElement("Body", "");
            body.addChild(new XElement("tellNo", bankFront.operator));
            body.addChild(new XElement("nodeNo", nodeNo));// 机构标识
            body.addChild(new XElement("tranCode", "YQCZ03"));// 交易代码
            // 财政流水号：系统简称+年度日期+8位流水。如：pj+170314+00000001
            String transferFlowNo;
            String systemEasyName = getBankConfig().getMapValueByKey("systemEasyName", nodeNo);
            if (StringHelper.isNullOrEmpty(systemEasyName)) {
                throw new Exception("systemEasyName标签项未配置，nodeNo标签值:" + nodeNo + "的系统简称");
            }
            transferFlowNo = systemEasyName + Format.Date6Format.format(Format.Date10Format.parse(p_req1908.singleDetail.payDate));
            int flowLength = p_req1908.singleDetail.askNumber.length();
            if (flowLength > 8) {
                transferFlowNo = transferFlowNo + p_req1908.singleDetail.askNumber.substring(flowLength - 8);
            } else {
                transferFlowNo = transferFlowNo + StringUtils.leftPad(p_req1908.singleDetail.askNumber, 8, "0");
            }
            JDBCHelper.update(conn, INSERTRECEIPT, new Object[]{transferFlowNo, p_req1908.reqHeader.bankCode, p_req1908.reqHeader.reqSeqID, transferFlowNo});
            body.addChild(new XElement("transferFlowNo", transferFlowNo));// 财政流水号
            body.addChild(new XElement("payAccount", p_req1908.singleDetail.payAct));// 付款账号
            body.addChild(new XElement("payAccountNm", p_req1908.singleDetail.payName));// 付款方户名

            String payAcctBrn = getBankConfig().getMapValueByKey("org", p_req1908.singleDetail.payAct);
            if(StringHelper.isNullOrEmpty(payAcctBrn)){
                throw new Exception("org标签项未配置账号：" + p_req1908.singleDetail.payAct + "的机构号");
            }
            body.addChild(new XElement("payAcctBrn", payAcctBrn));// 付款账户开户机构

            String cur = convertCurToBank(p_req1908.singleDetail.payCur);
            body.addChild(new XElement("currencyType", cur));
            String recAccount = p_req1908.singleDetail.recAct;
            body.addChild(new XElement("recAccount", recAccount));// 收方账户
            String recAccountName = p_req1908.singleDetail.recName;
            body.addChild(new XElement("recAccountName", recAccountName));// 收款方户名
            String recOpenBrn = p_req1908.singleDetail.cnapsCode;
            body.addChild(new XElement("recOpenBrn", recOpenBrn));// 收款方开户行行号
            String recOpenBrnName = p_req1908.singleDetail.cnapsName;
            body.addChild(new XElement("recOpenBrnName", recOpenBrnName));// 收款方开户行行名
            body.addChild(new XElement("recBrn", recOpenBrn));// 接收行号
            body.addChild(new XElement("recBrnName", recOpenBrnName));// 接受行名
            String transferAmt = p_req1908.singleDetail.payAmount;
            body.addChild(new XElement("transferAmt", transferAmt));// 交易金额
            body.addChild(new XElement("payUse", p_req1908.singleDetail.purpose));// 事由
            //是否加急
            body.addChild(new XElement("transferWay", p_req1908.singleDetail.paySpd));// 处理方式
            String tranType;
            if ("1".equals(p_req1908.singleDetail.sameBnk)) {
                tranType = "00";// 行内
            } else {
                //默认大额支付
                tranType = "12";// 跨行大额
            }
            body.addChild(new XElement("tranType", tranType));
            body.addChild(new XElement("payFee", "")); // 手续费
            body.addChild(new XElement("nextDayFlag", ""));// 次日到账标志
            String allStr = bankFront.operator + nodeNo + "YQCZ03" + transferFlowNo;
            // 加签
            String signStr = Decipher.sign(allStr, pfx);
            body.addChild(new XElement("signature", signStr));
            xmlTextWriter.writeXElement(body);
            xmlTextWriter.writeEndDocument();

            // 发送给银行
            String[] bankResult = sendToBank(xmlTextWriter.toXmlString(), cer);

            if (bankResult[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(bankResult[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String bankEncryptData = tmpBkReader.getFirstText("/root/encryptdata");
                    String bankEncryptKey = tmpBkReader.getFirstText("/root/encryptkey");
                    // 解密
                    String decryptData = decrypt(bankEncryptData, bankEncryptKey, pfx);
                    // 验签
                    if (checkBkSign(decryptData, cer)) {// 验签成功
                        StringBuilder tmpDecryptMsg = new StringBuilder();
                        XmlTextReader tmpReader = loadBankRespXmlReader(decryptData, tmpDecryptMsg);
                        String hostReturnCode = tmpReader.getFirstText("/root/hostReturnCode");
                        if ("0000".equals(hostReturnCode)) {
                            detail.respCode = "0";
                            detail.respInfo = tmpReader.getFirstText("/root/hostErrorMessage");
                            detail.transState = hostReturnCode;
                            detail.payInfoCode = hostReturnCode;
                            detail.outTransID = tmpReader.getFirstText("/root/coreFlowNo");
                        } else {
                            detail.respCode = "-1";
                            detail.respInfo = tmpReader.getFirstText("/root/hostErrorMessage");
                        }
                    } else {
                        detail.respCode = "-1";
                        detail.respInfo = "验签不通过";
                    }
                } else {
                    detail.respCode = "-1";
                    detail.respInfo = tmpSbMsg.toString();
                }
            } else if (ConnState.FAIL.equals(bankResult[0])) {
                detail.respCode = "0";
                detail.respInfo = bankResult[1];
                detail.reqSeqID = p_req1908.singleDetail.askNumber;
                detail.transState = PaymentState.FAIL_Payment;
                detail.payInfoCode = bankResult[0];
            } else {
                detail.respCode = "-1";
                detail.respInfo = bankResult[1];
            }

        } catch (Exception e) {
            detail.respCode = "-1";
            detail.respInfo = e.getMessage();
        } finally {
            conn.close();
        }
        retAts.writeRetDetail(detail);
        return retAts;
    }

    @Override
    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        String cer = getBankConfig().getValueAsString("certificatePath");
        String pfx = getBankConfig().getValueAsString("certificatePfxPath");
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        RetAtsSglDetail detail = new RetAtsSglDetail();
        Connection conn = FGBiz.getLocalDbConn();
        try {
            detail.reqSeqID = p_req1944.askNumber;
            XmlTextWriter xmlTextWriter = new XmlTextWriter();
            JHBANK02Header header = new JHBANK02Header();
            header.userid = bankFront.operator;
            String nodeNo = getBankConfig().getValueAsString("nodeNo");
            header.brchno = nodeNo;
            header.servtp = "";
            header.prcscd = "YQCZ04";
            writeCommenHeader(xmlTextWriter, header);

            xmlTextWriter.writeStartElement("Body");
            xmlTextWriter.writeElementString("tellNo", bankFront.operator, true);// 操作员号
            xmlTextWriter.writeElementString("nodeNo", nodeNo, true);// 机构标识
            xmlTextWriter.writeElementString("tranCode", "YQCZ04", true);// 交易代码
            Map<String, Object> map = JDBCHelper.execQuerySingle(conn, SELECTRECEIPT, new Object[]{p_req1944.askNumber, p_req1944.reqHeader.bankCode});
            if (map.size() == 0) {
                detail.respCode = "-1";
                detail.respInfo = "没有这条请求映射的流水号！";
                retAts.writeRetDetail(detail);
                return retAts;
            }
            String transferFlowNo = map.get("BANKREQSEQID").toString();// 财政流水号

            xmlTextWriter.writeElementString("transferFlowNo", transferFlowNo, true);
            String allStr = bankFront.operator + nodeNo + "YQCZ04" + transferFlowNo;
            // 加签
            String signStr = Decipher.sign(allStr, pfx);
            xmlTextWriter.writeElementString("signature", signStr);
            xmlTextWriter.writeEndDocument();
            // 发送给银行
            String[] bankResult = sendToBank(xmlTextWriter.toXmlString(), cer);

            if (bankResult[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(bankResult[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    // 获得密文秘钥
                    String bankEncryptData = tmpBkReader.getFirstText("/root/encryptdata");
                    String bankEncryptKey = tmpBkReader.getFirstText("/root/encryptkey");
                    // 解密
                    String decryptData = decrypt(bankEncryptData, bankEncryptKey, pfx);
                    // 验签
                    if (checkBkSign(decryptData, cer)) {
                        StringBuilder tmpDecryptMsg = new StringBuilder();
                        XmlTextReader tmpReader = loadBankRespXmlReader(decryptData, tmpDecryptMsg);
                        String hostReturnCode = tmpReader.getFirstText("/root/hostReturnCode");
                        String retMsg = tmpReader.getFirstText("/root/remark");
                        if (StringHelper.isNullOrEmpty(retMsg)) {
                            retMsg = tmpReader.getFirstText("/root/hostErrorMessage");
                        }
                        if ("0000".equals(hostReturnCode)) {
                            detail.respCode = "0";
                            detail.respInfo = retMsg;// ("/root/hostReturnCode");
                            // 交易状态  3：已成功   0：主机处理中  2：交易失败  4：异常
                            detail.transState = hostReturnCode + "+" + tmpReader.getFirstText("/root/transt");
                            detail.payInfoCode = detail.transState;
                            detail.outTransID = tmpReader.getFirstText("/root/coreFlowNo");// 订单号、流水号
                        } else {
                            detail.respCode = "-1";
                        }
                    } else {
                        detail.respCode = "-1";
                        detail.respInfo = "验签不通过";
                    }
                } else {
                    detail.respCode = "-1";
                    detail.respInfo = tmpSbMsg.toString();
                }
            } else {
                detail.respCode = "-1";
                detail.respInfo = bankResult[1];
            }
        } catch (Exception ex) {
            detail.respCode = "-1";
            detail.respInfo = ex.getMessage();
        } finally {
            conn.close();
        }
        retAts.writeRetDetail(detail);
        return retAts;
    }

    @Override
    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        return null;
    }

    @Override
    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        return null;
    }
}
